/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package officeboost.domain;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import officeboost.entity.Group;
import officeboost.entity.form.AbstractForm;
import officeboost.entity.form.LeaveForm;
import officeboost.util.FormTypes;
import officeboost.util.ObConstants;
import org.jbpm.api.Execution;
import org.jbpm.api.task.Task;

/**
 *
 * @author sorra
 */
@Singleton
@LocalBean
public class OfficeMgr {

    @EJB
    ProcessMgr pm;
    @EJB
    PersonService personService;
    @PersistenceContext
    EntityManager em;
    Map<String, Lock> lockMap = new HashMap<>();
    @EJB
    LogMgr logger;

    //web层new出具体表单，填上申请信息，传到这里
    public void apply(String uid, AbstractForm form) {
	//TODO: apply with a form

	em.persist(form);

	String processInstanceId = form.apply(pm.getExecutionService());
	logger.log("-ProcessInstance started: " + processInstanceId);
	logger.log("完成apply");
    }

    public List<ApplyPack> getApplyList(String uid) {
	List<ApplyPack> applyList = new ArrayList<>();

	for (FormTypes ft : FormTypes.values()) {
	    Query query = em.createQuery("from " + ft.toString() + " f where f.uid='" + uid+"'");
	    logger.log(query.toString());
	    List<AbstractForm> forms = query.getResultList();
	    for (AbstractForm form : forms) {
		applyList.add(new ApplyPack(ft.toString(), form));
	    }
	}
	return applyList;
    }

    public List<TaskInfo> getTaskList(String uid) {
	List<TaskInfo> taskList = new ArrayList<>();
	List<Task> jbpmTasks = new ArrayList<>();

	//收集该用户的任务列表

	List<Group> groups = personService.findGroupsByUser(personService.find(uid));

	logger.log("successfully find groups in getTaskList");
	for (Group group : groups) {
	    jbpmTasks.addAll(pm.getTaskService().findPersonalTasks(group.getName()));
	}

	//过滤掉已锁的任务，只返回无锁的任务
	for (int i = 0; i < jbpmTasks.size(); i++) {
	    String taskId = jbpmTasks.get(i).getId();
	    if (lockMap.containsKey(taskId) == false || lockMap.get(taskId).getUid().equals(uid)) {
		TaskInfo taskInfo = new TaskInfo(taskId, getFormTypeByTaskId(taskId));
		taskList.add(taskInfo);
	    } else {
		logger.log("过滤了被锁定的任务：" + taskId);
	    }
	}

	logger.log("完成getTaskList");
	return taskList;
    }

    //
    public TaskPack getTask(String taskId, String uid) {
	Task task = pm.getTaskService().getTask(taskId);
	//加锁
	lockMap.put(taskId, new Lock(taskId, uid));

	AbstractForm form = findFormByTaskId(taskId);

	logger.log("完成getTask");
	return new TaskPack(new TaskInfo(taskId, getFormTypeByTaskId(taskId)), form);
    }

    public ApplyPack getApply(String formType, String formId) {

	AbstractForm form = null;
	try {
	    Query query = em.createQuery("from " + formType + " f where f.id=" + formId);
	    form = (AbstractForm) query.getSingleResult();
//	    form = (IForm) em.find(Class.forName(formEntityName), formId);
	} catch (Exception ex) {
	    logger.log(ex.getMessage());
	    logger.log("Apply Form entity not found: " + formType + "! Please check.");
	}

	if (form == null) {
	    logger.log("糟糕 apply form is null!");
	}
	return new ApplyPack(formType, form);
    }

    public int successFormNum(String formType) {
	int result = 0;
	Query query = em.createQuery("from " + formType + " f where f.status=" + ObConstants.PASSED);
	result = query.getResultList().size();
	return result;
    }

    public int failedFormNum(String formType) {
	int result = 0;
	Query query = em.createQuery("from " + formType + " f where f.status=" + ObConstants.FAILED);
	result = query.getResultList().size();
	return result;
    }

    public int goingFormNum(String formType) {
	int result = 0;
	Query query = em.createQuery("from " + formType + " f where f.status=" + ObConstants.GOING);
	result = query.getResultList().size();
	return result;
    }

    public int formNum(String formType) {
	int result = 0;
	Query query = em.createQuery("from " + formType + " f");
	result = query.getResultList().size();
	return result;
    }

    //批复
    public void submitTask(String taskId, boolean approve, AbstractForm form) {
	String choice;
	if (approve) {
	    choice = "accept";
	} else {
	    choice = "reject";
	}
	pm.getTaskService().completeTask(taskId, choice);

	em.merge(form);
    }

    //从流程表名查找表单类时，可能产生ClassNotFoundException
    private AbstractForm findFormByTaskId(String taskId) {
	long formId = getFormIdByTaskId(taskId);
	String formType = getFormTypeByTaskId(taskId);
	logger.log("Looking for Form id=" + formId + " type=" + formType);

	AbstractForm form = null;
	try {
	    Query query = em.createQuery("from " + formType + " f where f.id=" + formId);
	    form = (AbstractForm) query.getSingleResult();
//	    form = (IForm) em.find(Class.forName(formEntityName), formId);
	} catch (Exception ex) {
	    logger.log(ex.getMessage());
	    logger.log("Form entity not found: " + formType + "! Please check.");
	}

	if (form == null) {
	    logger.log("糟糕 form is null!");
	}
	return form;
    }

    private long getFormIdByTaskId(String taskId) {
	Task task = pm.getTaskService().getTask(taskId);
	Execution execution = pm.getExecutionService().findExecutionById(task.getExecutionId());
	return Long.parseLong(execution.getKey());
    }

    private String getFormTypeByTaskId(String taskId) {
	Task task = pm.getTaskService().getTask(taskId);
	Execution execution = pm.getExecutionService().findExecutionById(task.getExecutionId());
	String pdId = execution.getProcessDefinitionId();

	return pdId.substring(0, pdId.lastIndexOf('-'));
    }

    public String testApp() {
	String app = "testApp begins!";

	LeaveForm form1 = new LeaveForm();
	form1.setName("student0");
	form1.setReason("我有事");
	apply("student0", form1);
	List<TaskInfo> taskList = getTaskList("teacher10");

	for (TaskInfo taskInfo : taskList) {
	    app += "<p>" + taskInfo.toString() + "</p>";
	    logger.log("<p>" + taskInfo.toString() + "</p>");
	}
	TaskPack taskPack = getTask(taskList.get(0).getTaskId(), "teacher10");
	logger.log(taskPack.getTaskInfo().toString());

	List<ApplyPack> applyList = getApplyList("student0");
	logger.log("ApplyList size: " + applyList.size());

	return app;
    }
}
